/**
* 版权归 瞄你个汪 所有。
* 使用本代码应遵守相关法律法规和许可证的要求。
*/
package cn.sqlsuper.toolkit;

import cn.hutool.core.util.ClassUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * SpringBoot 管理工具类
 * </p>
 * @author 瞄你个汪
 * @since 2024-05-01 12:00:00
 */
@Slf4j
@Component
@Lazy(false)
public class SpringBeanManager implements ApplicationContextAware {
    @Getter
    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringBeanManager.applicationContext = applicationContext;
    }

    /**
     * 根据类型名称获取Spring Bean
     * @param className 类型名称
     * @return 继承T的Spring Bean
     * @param <T> Bean对应的类
     */
    public static <T> T getBean(String className) {
        return applicationContext.getBean(ClassUtil.loadClass(className));
    }

    /**
     * 根据类型获取Spring Bean
     * @param clazz 类型
     * @return 继承T的Spring Bean
     * @param <T> Bean对应的类
     */
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    /**
     * 根据类型获取所有继承基类的Spring Bean
     * @param clazz 基类类型
     * @return 所有继承T的Spring Bean
     * @param <T> 基类
     */
    public static <T> List<T> getBeans(Class<T> clazz) {
        ConfigurableListableBeanFactory factory = (ConfigurableListableBeanFactory)applicationContext.getAutowireCapableBeanFactory();

        List<T> beansOfType = new ArrayList<>();
        for (String beanName : factory.getBeanDefinitionNames()) {
            try {
                Class<T> beanType = ClassUtil.loadClass(beanName);
                if (beanType != null && clazz.isAssignableFrom(beanType)) {
                    beansOfType.add(applicationContext.getBean(beanType));
                }
            } catch (Exception ignored) { }
        }
        return beansOfType;
    }
}
